-
Notifications
You must be signed in to change notification settings - Fork 327
Playground CLI Allow /wordpress subdirs to be mounted before WP install #2382
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Confirming that this PR fixes the issue I was having (trying to mount an existing |
const moveRecursively = (source: string, target: string, php: PHP) => { | ||
if (php.fileExists(target)) { | ||
/* | ||
* Something exists at the target path. | ||
* Let's check to make sure we aren't copying conflicting types. | ||
* | ||
* In this context, if the source path points to a file and the | ||
* target path points to a directory, we do not intend for the file | ||
* to be moved into the directory. | ||
*/ | ||
|
||
if (!php.isDir(source) && php.isDir(target)) { | ||
throw new Error( | ||
`The target ${target} is a directory but the source ${source} is not. This is not supported.` | ||
); | ||
} | ||
if (php.isDir(source) && !php.isDir(target)) { | ||
throw new Error( | ||
`The source ${source} is a directory but the target ${target} is not. This is not supported.` | ||
); | ||
} | ||
} | ||
|
||
if (isNonEmptyDir(target, php)) { | ||
// We cannot move a directory over a non-empty directory, | ||
// so we move the children one by one. | ||
for (const file of php.listFiles(source)) { | ||
const sourcePath = joinPaths(source, file); | ||
const targetPath = joinPaths(target, file); | ||
moveRecursively(sourcePath, targetPath, php); | ||
} | ||
} else { | ||
php.mv(source, target); | ||
} | ||
php.rmdir(wpPath, { recursive: true }); | ||
} else { | ||
php.mv(wpPath, php.documentRoot); | ||
}; | ||
try { | ||
moveRecursively(wpPath, php.documentRoot, php); | ||
// Remove any directories left because there were existing dirs at the target path. | ||
if (php.fileExists(wpPath)) { | ||
php.rmdir(wpPath, { recursive: true }); | ||
} | ||
} catch (e) { | ||
throw e; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would fit nicely into FSHelpers
, similarly to how we have copyRecursive
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And mount tests have a bunch of FS related tests, so they could be a good fit for adding tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please just confirm that we are correctly moving links like we do here https://github.com/WordPress/wordpress-playground/blob/trunk/packages/php-wasm/universal/src/lib/fs-helpers.ts#L303
This unzip process may be replaced by @adamziel's Blueprints v2 work. I will test with that PR and see if the problem persists there. |
I tested with Blueprints V2 and encountered the following error: "The target site root directory must be empty in the create-new-site mode, but it wasn't." Let's take a look at what v2 Blueprint or CLI args would be good for this use case. Maybe mounting a dir before WP install is not the right thing to do. Original note here. |
Let's still ship it as it fixes an important Blueprints v1 problem. We can address v2 as a follow-up. It's as much a technical question as it is a specification question, e.g. maybe requiring an empty directory for new site creation isn't a useful constraint. |
const sourcePath = joinPaths(wpPath, file); | ||
const targetPath = joinPaths(php.documentRoot, file); | ||
php.mv(sourcePath, targetPath); | ||
const moveRecursively = (source: string, target: string, php: PHP) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far, I've avoided moving this into FS helpers because it is an odd sort of operation:
Move a single directory, or if a directory already exists at the target path, move its children.
If there are existing files at the target paths, those files will be left intact, and the source files will not be moved. (But they will be deleted as leftovers of the unzipped WP dir later on.)
if (php.fileExists(target) && !php.isDir(target)) { | ||
// Refuse to overwrite existing files to avoid the chance of data loss. | ||
const wpPath = source.replace( | ||
/^\/tmp\/unzipped-wordpress\//, | ||
'/' | ||
); | ||
logger.warn( | ||
`Skipping ${wpPath} because a file exists at the target path.` | ||
); | ||
return; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm concerned that we might overwrite existing files. It is an mv
-style operation, but the FSHelpers.mv()
copies recursively if moving between different filesystems. And that can result in user data loss.
So we are skipping files that already exist.
Motivation for the change, related issues
In Playground CLI, /wordpress subdirs cannot currently be mounted before WP install because unzipping the WordPress zip fails. See #2381 for details.
Fixes #2381
Implementation details
The PR allows moving WordPress source files over an existing directory structure with some restrictions.
I'm a bit concerned it could lead to folks unintentionally overwriting their own files, so I'm not 100% we should land this. But let's discuss and find a path forward.
Testing Instructions (or ideally a Blueprint)